package com.campus.counseling.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.campus.counseling.entity.*;
import com.campus.counseling.model.common.exception.BusinessException;
import com.campus.counseling.model.common.exception.ServiceException;
import com.campus.counseling.model.dto.DistributeIncomeDTO;
import com.campus.counseling.model.dto.DistributeRecordDTO;
import com.campus.counseling.model.dto.RefundFormDTO;
import com.campus.counseling.model.mapper.PaymentRecordMapper;
import com.campus.counseling.model.vo.PaymentRecordVO;
import com.campus.counseling.security.SecurityUser;
import com.campus.counseling.service.*;
import com.campus.counseling.util.SecurityUtils;
import com.campus.counseling.model.vo.PaymentRecordVO;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class PaymentServiceImpl extends ServiceImpl<PaymentRecordMapper, PaymentRecord> implements PaymentService {

    private static final Logger log = LoggerFactory.getLogger(PaymentServiceImpl.class);

    private final AppointmentStatusService appointmentStatusService;
    private final CounselorPriceService counselorPriceService;
    private final PaymentRecordMapper paymentRecordMapper;
    private final AlipayHelper alipayHelper;
    private final AppointmentService appointmentService;
    private final PlatformAccountService platformAccountService;
    private final ChatService chatService;
    private final ConsultationRecordService consultationRecordService;

    @Override
    @Transactional
    public String createPayment(String appointmentInfo) {
        try {
            // 解析预约信息
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> appointmentData = mapper.readValue(appointmentInfo, Map.class);

            // 获取咨询师价格
            Long counselorId = Long.valueOf(appointmentData.get("counselorId").toString());
            CounselorPrice price = counselorPriceService.getPriceByCounselorId(counselorId);
            if (price == null) {
                throw new ServiceException("咨询师未设置价格");
            }

            // 创建支付记录
            PaymentRecord payment = new PaymentRecord();
            payment.setStudentId(SecurityUtils.getUserId());
            payment.setCounselorId(counselorId);
            payment.setOrderNo(generateOrderNo());
            payment.setTotalAmount(price.getPricePerHour());
            payment.setAppointmentInfo(appointmentInfo);

            // 计算平台费用和咨询师收入
            payment.setPlatformFee(calculatePlatformFee(price.getPricePerHour()));
            payment.setCounselorAmount(price.getPricePerHour().subtract(payment.getPlatformFee()));

            payment.setPaymentMethod("ALIPAY");
            payment.setPaymentStatus("PENDING");
            payment.setCreateTime(LocalDateTime.now());
            payment.setUpdateTime(LocalDateTime.now());

            save(payment);

            // 生成支付宝订单
            String description = "心理咨询预约-" + appointmentData.get("appointmentTime");
            return alipayHelper.createOrder(payment.getOrderNo(), payment.getTotalAmount(), description);
        } catch (Exception e) {
            log.error("创建支付订单失败", e);
            throw new ServiceException("创建支付订单失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public void handlePaymentNotify(Map<String, String> params) {
        try {
            String orderNo = params.get("out_trade_no");
            String tradeStatus = params.get("trade_status");
            String tradeNo = params.get("trade_no");

            PaymentRecord payment = getByOrderNo(orderNo);
            if (payment == null) {
                log.error("支付记录不存在：{}", orderNo);
                throw new ServiceException("支付记录不存在");
            }

            if ("SUCCESS".equals(payment.getPaymentStatus())) {
                log.info("订单{}已经支付成功，无需重复处理", orderNo);
                return;
            }

            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                // 更新支付记录状态
                payment.setPaymentStatus("SUCCESS");
                payment.setTransactionId(tradeNo);
                payment.setPaymentTime(LocalDateTime.now());
                payment.setUpdateTime(LocalDateTime.now());
                updateById(payment);

                // 创建预约记录
                Appointment appointment = createAppointment(payment);
                log.info("已创建预约记录，ID：{}", appointment.getId());

                // 处理资金分配
                handleFundDistribution(payment);
            }
        } catch (Exception e) {
            log.error("处理支付通知失败", e);
            throw new ServiceException("处理支付通知失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public void handlePaymentReturn(Map<String, String> params) {
        log.info("处理支付宝同步返回：{}", params);

        try {
            // 获取返回数据
            String orderNo = params.get("out_trade_no");
            String tradeNo = params.get("trade_no");
            String tradeStatus = params.get("trade_status");

            log.info("订单号：{}，支付宝交易号：{}，交易状态：{}", orderNo, tradeNo, tradeStatus);

            // 查询支付记录
            PaymentRecord payment = getByOrderNo(orderNo);
            if (payment == null) {
                log.error("支付记录不存在：{}", orderNo);
                throw new ServiceException("支付记录不存在");
            }

            // 如果已经是成功状态，直接返回
            if ("SUCCESS".equals(payment.getPaymentStatus())) {
                log.info("订单{}已经支付成功，无需重复处理", orderNo);
                return;
            }

            // 更新支付记录状态
            payment.setPaymentStatus("SUCCESS");
            payment.setTransactionId(tradeNo);
            payment.setPaymentTime(LocalDateTime.now());
            payment.setUpdateTime(LocalDateTime.now());
            boolean updated = updateById(payment);
            log.info("更新支付记录状态：{}", updated ? "成功" : "失败");

            // 更新预约状态
            appointmentStatusService.confirmAppointment(payment.getAppointmentId());

            // 处理资金分配
            handleFundDistribution(payment);

        } catch (Exception e) {
            log.error("处理支付返回失败", e);
            throw new ServiceException("处理支付返回失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public void refund(RefundFormDTO refundFormDTO) {
        PaymentRecord payment = getByOrderNo(refundFormDTO.getOrderNo());
        if (payment == null) {
            throw new ServiceException("支付记录不存在");
        }
        
        // 如果不是成功状态，不能申请退款
        if (!"SUCCESS".equals(payment.getPaymentStatus())) {
            throw new ServiceException("当前支付状态不支持退款");
        }

        // 如果已经有退款申请，不能重复申请
        if (payment.getRefundStatus() != null) {
            throw new ServiceException("已存在退款申请，请勿重复提交");
        }
        
        try {
            // 更新支付记录状态为退款申请中
            payment.setRefundStatus("PENDING");  // 退款状态：申请中
            payment.setRefundReason(refundFormDTO.getReason());
            payment.setRefundAmount(refundFormDTO.getAmount());
            payment.setContactPhone(refundFormDTO.getPhone());
            payment.setUpdateTime(LocalDateTime.now());
            updateById(payment);
            
            log.info("退款申请提交成功，订单号：{}，退款金额：{}", payment.getOrderNo(), refundFormDTO.getAmount());
            
        } catch (Exception e) {
            log.error("提交退款申请失败", e);
            throw new ServiceException("提交退款申请失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public void approveRefund(String orderNo, boolean approved, String remark) {
        PaymentRecord payment = getByOrderNo(orderNo);
        if (payment == null) {
            throw new ServiceException("支付记录不存在");
        }

        if (!"PENDING".equals(payment.getRefundStatus())) {
            throw new ServiceException("当前退款状态不支持此操作");
        }

        try {
            if (approved) {
                // 调用支付宝退款接口
                alipayHelper.refund(payment.getOrderNo(), payment.getRefundAmount(), payment.getRefundReason());

                // 更新支付记录状态
                payment.setPaymentStatus("REFUNDED");
                payment.setRefundStatus("APPROVED");
                payment.setRefundTime(LocalDateTime.now());
                log.info("退款审核通过，订单号：{}，退款金额：{}", payment.getOrderNo(), payment.getRefundAmount());
            } else {
                // 拒绝退款
                payment.setRefundStatus("REJECTED");
                log.info("退款审核拒绝，订单号：{}", payment.getOrderNo());
            }

            payment.setRemark(remark);
            payment.setUpdateTime(LocalDateTime.now());
            updateById(payment);

        } catch (Exception e) {
            log.error("处理退款申请失败", e);
            throw new ServiceException("处理退款申请失败：" + e.getMessage());
        }
    }

    private void handleFundDistribution(PaymentRecord payment) {
        // TODO: 实现资金分配逻辑
        // 1. 更新平台账户余额
        // 2. 更新咨询师账户余额
        // 3. 记录资金流水
    }

    @Override
    public PaymentRecord getByOrderNo(String orderNo) {
        return getOne(new LambdaQueryWrapper<PaymentRecord>()
                .eq(PaymentRecord::getOrderNo, orderNo));
    }

    @Override
    public Page<PaymentRecordVO> getPaymentPage(Integer pageNum, Integer pageSize, String orderNo, String status) {
        Page<PaymentRecord> page = new Page<>(pageNum, pageSize);
        return paymentRecordMapper.selectPaymentPage(page, orderNo, status);
    }

    @Override
    public Page<PaymentRecord> getStudentPayments(Integer pageNum, Integer pageSize) {
        return page(new Page<>(pageNum, pageSize),
            new LambdaQueryWrapper<PaymentRecord>()
                .eq(PaymentRecord::getStudentId, SecurityUtils.getUserId())
                .orderByDesc(PaymentRecord::getCreateTime));
    }

    @Override
    public Page<PaymentRecordVO> getCounselorPayments(Integer pageNum, Integer pageSize) {
        return paymentRecordMapper.selectCounselorPayments(
            new Page<>(pageNum, pageSize),
            SecurityUtils.getUserId()
        );
    }

    @Override
    public List<PaymentRecord> getPaymentsByDate(LocalDate date) {
        return list(new LambdaQueryWrapper<PaymentRecord>()
            .ge(PaymentRecord::getCreateTime, date.atStartOfDay())
            .lt(PaymentRecord::getCreateTime, date.plusDays(1).atStartOfDay()));
    }

    @Override
    public PaymentRecord getByAppointmentId(Long appointmentId) {
        return getOne(new LambdaQueryWrapper<PaymentRecord>()
            .eq(PaymentRecord::getAppointmentId, appointmentId));
    }

    private String generateOrderNo() {
        return UUID.randomUUID().toString().replace("-", "").substring(0, 32);
    }

    private BigDecimal calculatePlatformFee(BigDecimal amount) {
        // 获取平台账户信息
        PlatformAccount account = platformAccountService.getAccount();
        if (account == null || account.getPlatformFeeRate() == null) {
            log.warn("平台费率未设置，使用默认费率20%");
            return amount.multiply(new BigDecimal("0.20")).setScale(2, RoundingMode.HALF_UP);
        }
        
        // 将百分比转换为小数（因为存储的是百分比形式，如：20.00 表示 20%）
        BigDecimal feeRate = account.getPlatformFeeRate().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
        return amount.multiply(feeRate).setScale(2, RoundingMode.HALF_UP);
    }

    @Override
    public Page<PaymentRecordVO> getIncomeList(Integer pageNum, Integer pageSize, String orderNo, 
            String counselorName, String status, String startDate, String endDate) {
        Page<PaymentRecord> page = new Page<>(pageNum, pageSize);
        return paymentRecordMapper.getIncomeList(page, orderNo, counselorName, status, startDate, endDate);
    }

    @Override
    public Map<String, Object> getIncomeStatistics() {
        Map<String, Object> stats = paymentRecordMapper.getIncomeStatistics();
        // 计算环比增长
        Map<String, Object> lastMonthStats = paymentRecordMapper.getLastMonthIncomeStatistics();
        if (stats != null && lastMonthStats != null) {
            calculateIncrease(stats, lastMonthStats);
        }
        return stats;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void distributeIncome(DistributeIncomeDTO dto) {
        // 获取当前操作用户
        SecurityUser currentUser = SecurityUtils.getLoginUser();
        if (currentUser == null) {
            throw new ServiceException("用户未登录");
        }
        String operatorName = currentUser.getUsername();
        Date now = new Date();

        if (dto.getRecords() != null && !dto.getRecords().isEmpty()) {
            // 批量分发
            for (DistributeRecordDTO record : dto.getRecords()) {
                updateDistributionStatus(record.getOrderNo(), operatorName, dto.getRemark(), now);
            }
        } else {
            // 单条分发
            updateDistributionStatus(dto.getOrderNo(), operatorName, dto.getRemark(), now);
        }
    }

    private void updateDistributionStatus(String orderNo, String operatorName, String remark, Date distributionTime) {
        int rows = paymentRecordMapper.updateDistributionStatus(orderNo, "DISTRIBUTED", distributionTime, operatorName, remark);
        if (rows == 0) {
            throw new BusinessException("订单状态已变更，请刷新后重试");
        }
    }

    private void calculateIncrease(Map<String, Object> current, Map<String, Object> last) {
        BigDecimal currentTotal = (BigDecimal) current.get("totalAmount");
        BigDecimal lastTotal = (BigDecimal) last.get("totalAmount");
        if (currentTotal != null && lastTotal != null && lastTotal.compareTo(BigDecimal.ZERO) != 0) {
            BigDecimal increase = currentTotal.subtract(lastTotal).multiply(new BigDecimal("100"))
                    .divide(lastTotal, 2, RoundingMode.HALF_UP);
            current.put("totalIncrease", increase);
        }

        BigDecimal currentPlatform = (BigDecimal) current.get("platformIncome");
        BigDecimal lastPlatform = (BigDecimal) last.get("platformIncome");
        if (currentPlatform != null && lastPlatform != null && lastPlatform.compareTo(BigDecimal.ZERO) != 0) {
            BigDecimal increase = currentPlatform.subtract(lastPlatform).multiply(new BigDecimal("100"))
                    .divide(lastPlatform, 2, RoundingMode.HALF_UP);
            current.put("platformIncrease", increase);
        }
    }

    private Appointment createAppointment(PaymentRecord payment) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> appointmentData = mapper.readValue(payment.getAppointmentInfo(), Map.class);
            
            // 添加日期时间格式化
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
            LocalDateTime appointmentTime = LocalDateTime.parse(
                appointmentData.get("appointmentTime").toString(), 
                formatter
            );
            
            Appointment appointment = new Appointment();
            appointment.setStudentId(payment.getStudentId());
            appointment.setCounselorId(payment.getCounselorId());
            appointment.setPaymentId(payment.getId());
            appointment.setAppointmentTime(appointmentTime);
            appointment.setType(appointmentData.get("type").toString());
            appointment.setDescription(appointmentData.get("description").toString());
            appointment.setStatus("PENDING");  // 设置为待确认状态
            appointment.setCreateTime(LocalDateTime.now());
            appointment.setUpdateTime(LocalDateTime.now());
            
            appointmentService.save(appointment);
            
            // 更新支付记录关联的预约ID
            payment.setAppointmentId(appointment.getId());
            updateById(payment);
            
            log.info("成功创建预约记录，ID：{}", appointment.getId());
            return appointment;
        } catch (Exception e) {
            log.error("创建预约记录失败", e);
            throw new ServiceException("创建预约记录失败：" + e.getMessage());
        }
    }

    @Override
    public String getPaymentStatus(String orderNo) {
        PaymentRecord payment = getByOrderNo(orderNo);
        return payment != null ? payment.getPaymentStatus() : null;
    }

    @Override
    @Transactional
    public void cancelPayment(String orderNo) {
        PaymentRecord payment = getByOrderNo(orderNo);
        if (payment == null) {
            throw new ServiceException("订单不存在");
        }
        
        // 只有待支付状态的订单可以取消
        if (!"PENDING".equals(payment.getPaymentStatus())) {
            throw new ServiceException("当前订单状态不支持取消");
        }
        
        // 更新订单状态
        payment.setPaymentStatus("CANCELLED");
        payment.setUpdateTime(LocalDateTime.now());
        updateById(payment);
        
        // 如果有关联的预约记录，也需要取消
        if (payment.getAppointmentId() != null) {
            appointmentService.cancelAppointment(payment.getAppointmentId(), "订单已取消");
        }
        
        log.info("订单{}已取消", orderNo);
    }
} 